#include <winsock2.h>
#include <ws2tcpip.h>
#include <process.h>
#include <winsock.h>
#include <iostream>
#include <windows.h>
#include <sstream>
#include <string>
#include <fstream>
#include <stdio.h>
#include <vector>
#include <iterator>
#include "TcpServer.h"
#include "TcpThread.h"

using namespace std;

TcpServer::TcpServer()
{
	WSADATA wsadata;

	if (WSAStartup(0x0202, &wsadata) != 0){
		cout << "Error in starting WSAStartup()\n";
	}
	else{
		buffer = "WSAStartup was successful\n";
		WriteFile(test, buffer, sizeof(buffer), &dwtest, NULL);

		/* display the wsadata structure */
		cout << endl
			<< "wsadata.wVersion " << wsadata.wVersion << endl
			<< "wsadata.wHighVersion " << wsadata.wHighVersion << endl
			<< "wsadata.szDescription " << wsadata.szDescription << endl
			<< "wsadata.szSystemStatus " << wsadata.szSystemStatus << endl
			<< "wsadata.iMaxSockets " << wsadata.iMaxSockets << endl
			<< "wsadata.iMaxUdpDg " << wsadata.iMaxUdpDg << endl;
	}

	//Display info of local host
	gethostname(localhost, 10);
	cout << "hostname: " << localhost << endl;

	if ((hp = gethostbyname(localhost)) == NULL) {
		cout << "gethostbyname() cannot get local host info?"
			<< WSAGetLastError() << endl;
		exit(1);
	}

	//Create the server socket
	if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
		throw "can't initialize socket";
	// For UDP protocol replace SOCK_STREAM with SOCK_DGRAM 


	//Fill-in Server Port and Address info.
	sa.sin_family = AF_INET;
	sa.sin_port = htons(port);
	sa.sin_addr.s_addr = htonl(INADDR_ANY);


	//Bind the server port
	if (bind(s, (LPSOCKADDR)&sa, sizeof(sa)) == SOCKET_ERROR)
		throw "can't bind the socket";
	cout << "Bind was successful" << endl;

	//Successfull bind, now listen for client requests.

	if (listen(s, 10) == SOCKET_ERROR)
		throw "couldn't  set up listen on socket";
	else cout << "Listen was successful" << endl;

	FD_ZERO(&readfds);
}


TcpServer::~TcpServer()
{
	closesocket(s1);
	closesocket(s);
	WSACleanup();
}


void TcpServer::start()
{
	//wait loop
	while (1)
	{
		FD_SET(s, &readfds);  //always check the listener

		if (!(outfds = select(infds, &readfds, NULL, NULL, tp))) {}

		else if (outfds == SOCKET_ERROR) throw "failure in Select";

		else if (FD_ISSET(s, &readfds))  cout << "got a connection request" << endl;

		//Found a connection request, try to accept. 

		if ((s1 = accept(s, &ca.generic, &calen)) == INVALID_SOCKET)
			throw "Couldn't accept connection\n";

		//Connection request accepted.
		cout << "accepted connection from " << inet_ntoa(ca.ca_in.sin_addr) << ":"
			<< hex << htons(ca.ca_in.sin_port) << endl;

		TcpThread * pt = new TcpThread(s1);
		pt->start();
	}
}